package ade.prime.activity;

import java.util.ArrayList;
import java.util.List;

import ade.prime.activity.adapter.ScheduleListAdapter;
import ade.prime.model.AdeWebOptions;
import ade.prime.model.Schedule;
import ade.prime.model.ScheduleState;
import ade.prime.service.AdeWebServiceListener;
import ade.prime.service.ScheduleUpdateProgress;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;

public class ScheduleList extends AdeWebFragmentActivity
implements BundleExtraNames {
	
	@SuppressWarnings("hiding")
	protected static final String TAG = ScheduleList.class.getSimpleName() ;
	
	protected static final int N_PROGRESS_STEPS_PER_SCHEDULE_UPDATE = 
			ScheduleUpdateProgress.values().length ;
	
	protected static final int PROGRESS_UPDATE_DELAY = 10 ;
	
	private static final int REFRESH_ID = 1 ;
	
	protected int progress ;
	
	protected int nTotalSteps ;

	protected String scheduleName ;

	protected Schedule displayedSchedule ;

	protected ActionMode mActionMode ;

	protected ScheduleListAdapter adapter ;

	protected boolean actionModeEnabled ;
	
	protected List<Schedule> updateQueue ;
	
	protected Handler handler ;
	
	protected ProgressUpdateRunnable updateProgressBar = new ProgressUpdateRunnable() ;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState) ;
		this.setTheme(AdeWebOptions.getTheme(this)) ;
		
		//This has to be called before setContentView
		this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS) ;
		this.requestWindowFeature(Window.FEATURE_PROGRESS) ;

		this.getSupportActionBar().setSubtitle(R.string.ScheduleList_label) ;
		this.setContentView(R.layout.schedule_list) ;

		//XXX Temporary
		Button bdd = (Button) this.findViewById(R.id.bdd) ;
		final ScheduleList act = this ;
		bdd.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent(act, Bdd.class) ;
				act.startActivity(intent) ;
			}
		}) ;
		// ---------------
		this.updateQueue= new ArrayList<Schedule>() ;
		this.progress = 0 ;
		this.nTotalSteps = 0 ;
		this.handler = new Handler() ;
		
		// Hide schedule details and list framgent
		FragmentManager fm = this.getSupportFragmentManager() ;
		ScheduleDetailsFragment detailsFragment = 
				(ScheduleDetailsFragment) fm.findFragmentById(R.id.schedule_details) ;
		ScheduleListFragment listFragment = 
				(ScheduleListFragment) fm.findFragmentById(R.id.schedule_list) ;
		detailsFragment.setActivity(this) ;
		listFragment.setActivity(this) ;
		FragmentTransaction ft = fm.beginTransaction() ;
		if (!detailsFragment.isHidden()) {
			ft.hide(detailsFragment) ;
		}// if
		if (!listFragment.isHidden()) {
			ft.hide(listFragment) ;
		}// if
		ft.commit() ;
	}// onCreate(Bundle)

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		Intent createScheduleIntent = new Intent(this, CreateSchedule.class) ;
		Intent userManualIntent = new Intent(this, UserManual.class) ;
		Intent preferencesIntent = new Intent(this, Preference.class) ;

		int iconId = R.drawable.ic_action_refresh_holo_dark ;
		boolean isVisible = this.updateQueue.isEmpty()
				&& (this.updateProgressBar.currentProgress 
						>= android.view.Window.PROGRESS_END) ;
		menu.add(Menu.NONE, REFRESH_ID, Menu.NONE, R.string.ActionBar_refresh)
		.setIcon(iconId)
		.setVisible(isVisible)
		.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) ;
		
		menu.add(R.string.ActionBar_add)
		.setIcon(R.drawable.ic_action_new_holo_dark)
		.setIntent(createScheduleIntent)
		.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) ;

		menu.add(R.string.ActionBar_help)
		.setIcon(R.drawable.ic_action_help_holo_light)
		.setIntent(userManualIntent)
		.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER) ;
		
		menu.add(R.string.ActionBar_preferences)
		.setIcon(R.drawable.ic_action_settings_holo_light)
		.setIntent(preferencesIntent)
		.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER) ;

		return super.onCreateOptionsMenu(menu) ;
	}// onCreateOptionsMenu(Menu)
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
//		Log.d(TAG, "OptionMenuItemClick: " + item.getItemId()) ;
		if (item.getItemId() == REFRESH_ID) {
			if (this.updateQueue.isEmpty()) {
				// Rafraichissement de tous les emplois du temps
				int nSchedules = this.adapter.getCount() ;
				for(int s=0; s < nSchedules ; ++s) {
					Schedule schedule = this.adapter.getItem(s) ;
					this.updateSchedule(schedule) ;
				}// for
			} else {
				// Annulation du rafraichissement de tous les emplois du temps
				int nSchedules = this.adapter.getCount() ;
				for(int s=0; s < nSchedules ; ++s) {
					Schedule schedule = this.adapter.getItem(s) ;
					this.cancelScheduleUpdate(schedule) ;
				}// for
			}// if
			return true ;
		}// if
		
		return false ;
	}// onOptionsItemSelected(MenuItem)
	
	protected void updateSchedule(Schedule schedule) {
		try {
			this.serviceApi.updateSchedule(schedule) ;
		} catch (RemoteException re) {
			// TODO Auto-generated catch block
			Log.d(TAG, String.format(
					"Failed to add schedule '%s' (%s) to update queue.",  //$NON-NLS-1$
					schedule.getName(), Integer.valueOf(schedule.getId())),
				re) ; 
		}// try
	}// updateSchedule(Schedule)
	
	protected void cancelScheduleUpdate(Schedule schedule) {
		try {
			this.serviceApi.cancelScheduleUpdate(schedule) ;
		} catch (RemoteException re) {
			// TODO Auto-generated catch block
			Log.d(TAG, String.format(
					"Failed to remove schedule '%s' (%s) from update queue.",//$NON-NLS-1$
					schedule.getName(), Integer.valueOf(schedule.getId())),
				re) ; 
		}// try
	}// updateSchedule(Schedule)

	@Override
	protected ServiceConnection getServiceConnection() {
		return new ServiceConnectionAdapter(this) ;
	}// getServiceConnection()

	@Override
	protected AdeWebServiceListener getAdeWebServiceListener() {
		return new AdeWebServiceListenerAdapter(this) ;
	}// getAdeWebServiceListener()

	public static class ScheduleDetailsFragment extends SherlockFragment
	implements OnLongClickListener {

		private ScheduleList activity ;

		public ScheduleDetailsFragment(ScheduleList activity) {
			this() ;
			this.activity = activity ;
		}// ScheduleDetailsFragment(ScheduleList)

		public ScheduleDetailsFragment() {
			super() ;
		}// ScheduleDetailsFragment()

		/**
		 * @param activity the activity to set
		 */
		public void setActivity(ScheduleList activity) {
			this.activity = activity ;
		}// setActivity(ScheduleList)

		public void updateContent() {
			TextView tv ;
			View v = this.getView() ;

			if (this.activity.displayedSchedule != null) {				
				// Schedule name
				tv = (TextView) v.findViewById(
						R.id.schedule_details_name) ;
				if (tv != null) {
					tv.setText(this.activity.displayedSchedule.getName()) ;
				}// if

				// Last updated
				tv = (TextView) v.findViewById(
						R.id.schedule_details_last_update) ;
				if (tv != null) {
					String lastUpdate = this.activity.displayedSchedule.getLastUpdate() ;
					if (lastUpdate == null) {
						tv.setText(R.string.ScheduleDetails_never) ;
					} else {
						tv.setText(lastUpdate) ;
					}// if
				}// if

				// Resource
				tv = (TextView) v.findViewById(
						R.id.schedule_details_resources) ;
				if (tv != null) {
					tv.setText(this.activity.displayedSchedule.getResources()) ;
				}// if

				// Period
				tv = (TextView) v.findViewById(
						R.id.schedule_details_period) ;
				String periodTemplate = this.getResources().getString(
						R.string.ScheduleDetails_period_template) ;
				if (tv != null) {
					tv.setText(String.format(periodTemplate, 
							Integer.valueOf(this.activity.displayedSchedule.getPeriod()))) ;
				}// if

				// Project Id
				tv = (TextView) v.findViewById(
						R.id.schedule_details_project_id) ;
				if (tv != null) {
					tv.setText(this.activity.displayedSchedule
							.getProject().getTextId()) ;
				}// if

				// Creation date
				tv = (TextView) v.findViewById(
						R.id.schedule_details_created) ;
				if (tv != null) {
					tv.setText(this.activity.displayedSchedule.getCreated()) ;
				}// if
			}// if	
		}// updateContent()

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View v = inflater.inflate(
					R.layout.schedule_details, container, false) ;
			v.setOnLongClickListener(this) ;
			return v ;
		}// onCreateView(LayoutInflater, ViewGroup, Bundle)

		@Override
		public boolean onLongClick(View v) {
//			FragmentManager fm = this.getActivity().getSupportFragmentManager() ;
//			Fragment detailsFragment = fm.findFragmentById(R.id.schedule_details) ;
//			Fragment listFragment = fm.findFragmentById(R.id.schedule_list) ;
//			FragmentTransaction ft = fm.beginTransaction() ;
//			ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) ;
//
//			ft.hide(detailsFragment) ;
//			ft.show(listFragment) ;
			this.activity.mActionMode.finish() ;

//			ft.commit() ;

			return true ;
		}// onLongClick(View)

	}// class ScheduleDetailsFragment

	public static class ScheduleListFragment extends SherlockFragment
	implements OnClickListener, OnItemClickListener, OnItemLongClickListener {

		private ScheduleList activity ;

		private ScheduleListAdapter adapter ;

		public ScheduleListFragment(ScheduleList activity) {
			super() ;
			this.activity = activity ;
		}// ScheduleListFragment(ScheduleList)

		public ScheduleListFragment() {
			super() ;
		}// ScheduleListFragment()

		/**
		 * @param activity the activity to set
		 */
		public void setActivity(ScheduleList activity) {
			this.activity = activity ;
			this.activity.adapter = this.adapter ;
		}// setActivity(ScheduleList)

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View v = inflater.inflate(R.layout.welcome_screen, container, false) ;

			ListView list = (ListView) v.findViewById(R.id.scheduleList) ; 
			list.setEmptyView(v.findViewById(R.id.empty)) ;

			TextView addSchedule = (TextView) v.findViewById(R.id.add_schedule) ;
			addSchedule.setOnClickListener(this) ;

			this.adapter =	new ScheduleListAdapter(this.getActivity()) ;
			list.setAdapter(this.adapter) ;
			registerForContextMenu(list) ;
			list.setOnItemLongClickListener(this) ;
			list.setOnItemClickListener(this) ;

			return v ;
		}// onCreateView(LayoutInflater, ViewGroup, Bundle)

		/**
		 * Gère le click sur le texte de création d'un emploi du temps affiché
		 * lorsqu'il n'y a pas d'emploi du temps.
		 */
		@Override
		public void onClick(View v) {
			Intent intent = new Intent(this.getActivity(), CreateSchedule.class) ;
			this.startActivity(intent) ;
		}// onClick(View)

		/**
		 * Gère le click sur un item de la liste.
		 */
		@Override
		public void onItemClick(AdapterView<?> a, View v, int position, long id) {
			Intent intent = new Intent(this.getActivity(), ViewSchedule.class) ;
			Schedule schedule = this.adapter.getItem(position) ;
			intent.putExtra(EXTRA_SCHEDULE, schedule) ;
			intent.putExtra(EXTRA_SCHEDULE_UPDATE_SCHEDULED, 
					schedule.getState().equals(ScheduleState.WAITING_FOR_UPDATE)) ;
			this.startActivity(intent) ;
		}// onItemClick(AdapterView<?>, View, int, long)

		@Override
		public boolean onOptionsItemSelected(MenuItem item) {
			//TODO Handle click
			return super.onOptionsItemSelected(item) ;
		}// onContextItemSelected(MenuItem)

		@Override
		public boolean onItemLongClick(AdapterView<?> av, View v, int position,
				long id) { 
			this.activity.displayedSchedule = 
					this.activity.adapter.getItem(position) ;

			FragmentManager fm = this.getActivity().getSupportFragmentManager() ;
			ScheduleDetailsFragment detailsFragment = 
					(ScheduleDetailsFragment) fm.findFragmentById(R.id.schedule_details) ;
			Fragment listFragment = fm.findFragmentById(R.id.schedule_list) ;
			detailsFragment.updateContent() ;
			this.activity.updateActionModeState() ;
			this.activity.mActionMode = this.activity.startActionMode(
					new ScheduleActionMode(this.activity)) ;

			FragmentTransaction ft = fm.beginTransaction() ;
			ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) ;
			ft.show(detailsFragment) ;
			ft.hide(listFragment) ;
			ft.commit() ;

			return true ;
		}// onItemLongClick(AdapterView<?>, View, int, long)

	}// class ScheduleListFragment

	private static final class ScheduleActionMode implements ActionMode.Callback {

		protected static final int MODIFY_ID = 0 ;

		protected static final int UPDATE_ID = 1 ;

		protected static final int DELETE_ID = 2 ;

		protected static final int HELP_ID = 3 ;

		private ScheduleList activity ;

		public ScheduleActionMode(ScheduleList activity) {
			super() ;
			this.activity = activity ;
		}// ScheduleActionMode(ScheduleList)

		@Override
		public boolean onCreateActionMode(ActionMode mode, Menu menu) {
			menu.add(Menu.NONE, MODIFY_ID, Menu.NONE, R.string.ActionBar_modify)
			.setIcon(R.drawable.ic_action_edit_holo_dark)
			.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) ;

			ScheduleState currentState = this.activity.displayedSchedule.getState() ;
			int itemId = currentState.equals(ScheduleState.WAITING_FOR_UPDATE) ?
					R.drawable.cancel : R.drawable.ic_action_refresh_holo_dark ;
			menu.add(Menu.NONE, UPDATE_ID, Menu.NONE, R.string.ActionBar_refresh)
			.setIcon(itemId)
			.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) ;

			menu.add(Menu.NONE, DELETE_ID, Menu.NONE, R.string.ActionBar_delete)
			.setIcon(R.drawable.ic_action_discard_holo_dark)
			.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) ;

			menu.add(Menu.NONE, HELP_ID, Menu.NONE, R.string.ActionBar_help)
			.setIcon(R.drawable.ic_action_help_holo_light)
			.setIntent(new Intent(this.activity, UserManual.class))
			.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER) ;
			
			return true ;
		}// onCreateActionMode(ActionMode, Menu)

		@Override
		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
			return true ;
		}// onPrepareActionMode(ActionMode, Menu)

		@Override
		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
			int itemId = item.getItemId() ;
			boolean consumeEvent = true ;
			if (itemId == HELP_ID) {
				consumeEvent = false ;
			} else if (itemId == UPDATE_ID) {
				ScheduleState state = this.activity.displayedSchedule.getState() ;
				if (state.equals(ScheduleState.WAITING_FOR_UPDATE)) {
					this.activity.cancelScheduleUpdate(this.activity.displayedSchedule) ;
				} else if (!state.equals(ScheduleState.UPDATING)) {
					this.activity.updateSchedule(this.activity.displayedSchedule) ;
				}// if
				consumeEvent = !state.equals(ScheduleState.UPDATING) ;
			} else if (this.activity.actionModeEnabled) {
				switch (itemId) {
				case MODIFY_ID:
					Intent editScheduleIntent = new Intent(
							this.activity, EditSchedule.class) ;
					editScheduleIntent.putExtra(
							EXTRA_SCHEDULE,
							this.activity.displayedSchedule) ;
					this.activity.startActivity(editScheduleIntent) ;
					break ;

				case DELETE_ID:
					this.activity.deleteSchedule() ;
					break ;

				}// switch
			} else {
				Toast.makeText(this.activity, 
						R.string.ScheduleList_action_not_available, 
						Toast.LENGTH_SHORT).show() ;
			}// if
			return consumeEvent ;
		}// onActionItemClicked(ActionMode, MenuItem)

		@Override
		public void onDestroyActionMode(ActionMode mode) {
			FragmentManager fm = this.activity.getSupportFragmentManager() ;
			Fragment detailsFragment = fm.findFragmentById(R.id.schedule_details) ;
			Fragment listFragment = fm.findFragmentById(R.id.schedule_list) ;
			FragmentTransaction ft = fm.beginTransaction() ;
			ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) ;

			if (!detailsFragment.isHidden()) {
				ft.hide(detailsFragment) ;
				ft.show(listFragment) ;
			}// if
			ft.commit() ;
			
			this.activity.displayedSchedule = null ;
			this.activity = null ;
		}// onDestroyActionMode(ActionMode)

	}// class ScheduleActionMode
	
	public void updateActionModeState() {
//		Log.d(TAG, "[updateActionModeState]") ;
		if (this.displayedSchedule != null) {
//			Log.d(TAG, "-- this.displayedSchedule not null =)") ;
			ScheduleState state = this.displayedSchedule.getState() ;
			this.actionModeEnabled = !state.equals(ScheduleState.UPDATING) ;
			if (this.mActionMode != null) {
//				Log.d(TAG, "-- this.mActionMode not null =)") ;
//				Log.d(TAG, "-- state: " + state) ;
				MenuItem item = this.mActionMode.getMenu()
						.getItem(ScheduleActionMode.UPDATE_ID) ;
				if (state.equals(ScheduleState.WAITING_FOR_UPDATE)) {
					item.setIcon(R.drawable.cancel) ;
				} else if ((state.equals(ScheduleState.UPDATING)
						|| state.equals(ScheduleState.UPDATED)
						|| state.equals(ScheduleState.NOT_UPDATED))) {
					item.setIcon(R.drawable.ic_action_refresh_holo_dark) ;
				}// if
			}// if
		}// if
	}// updateActionModeState()

	public void deleteSchedule() {
		final ScheduleList activity = this ;
		AlertDialog.Builder builder = new AlertDialog.Builder(this) ;
		String name = this.displayedSchedule.getName() ;
		String message = 
				this.getResources().getString(R.string.Schedule_delete_confirm_text) ;
		builder.setMessage(String.format(message, name))
		.setTitle(R.string.Schedule_delete_title) ;
		builder.setIcon(RESULT_OK) ;

		//Valider la suppression
		builder.setPositiveButton(R.string.Yes, new DialogInterface.OnClickListener() {
			//Supression de l'edt
			@Override
			public void onClick(DialogInterface dialog, int which) {
				try {
					activity.serviceApi.removeSchedule(activity.displayedSchedule) ;
				} catch (RemoteException re) {
					// TODO: handle exception
					Log.d(TAG, "Error deleting schedule " //$NON-NLS-1$ 
							+ activity.displayedSchedule.getName(), re) ;
				}// try
				activity.mActionMode.finish() ;
			}// onClick(DialogInterface, int)
		}) ;

		//Annuler la suppression
		builder.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss() ;
			}// onClick(DialogInterface, int)
		}) ;
		Dialog dialog = builder.create() ;
		dialog.show() ;
	}// deleteSchedule()

	protected class ServiceConnectionAdapter 
	extends AdeWebFragmentActivity.ServiceConnectionAdapter {

		protected ServiceConnectionAdapter(AdeWebFragmentActivity activity) {
			super(activity) ;
		}// ServiceConnectionAdapter(AdeWebFragmentActivity)

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			super.onServiceConnected(name, service) ;
			try {
				((ScheduleList) this.activity).adapter.setSchedules(
						this.activity.serviceApi.getAllSchedules()) ;
			} catch (RemoteException re) {
				// TODO: handle exception
				Log.d(TAG, "Error while retrieving all the schedules", //$NON-NLS-1$ 
						re) ;
			}// try
			this.activity.setSupportProgressBarIndeterminateVisibility(false) ;
			
			// Show list framgent
			FragmentManager fm = this.activity.getSupportFragmentManager() ;
			Fragment listFragment = fm.findFragmentById(R.id.schedule_list) ;
			FragmentTransaction ft = fm.beginTransaction() ;
			ft.show(listFragment) ;
			ft.commit() ;
		}// onServiceConnected(ComponentName, IBinder)

	}// class ServiceConnectionAdapter

	protected class AdeWebServiceListenerAdapter 
	extends AdeWebFragmentActivity.AdeWebServiceListenerAdapter {

		protected AdeWebServiceListenerAdapter(ScheduleList activity) {
			super(activity) ;
		}// AdeWebServiceListenerAdapter(ScheduleList)

		@Override
		public void handleNewScheduleRunnable(Schedule newSchedule) {
			ScheduleList sl = (ScheduleList) this.activity ;
			sl.adapter.addSchedule(newSchedule) ;
		}// handleNewScheduleRunnable(Schedule)

		@Override
		public void handleRemovedScheduleRunnable(Schedule removedSchedule) {
			ScheduleList sl = (ScheduleList) this.activity ;
			sl.adapter.removeSchedule(removedSchedule) ;
		}// handleRemovedScheduleRunnable(Schedule)
		
		@Override
		protected void handleModifiedScheduleRunnable(Schedule modifiedSchedule) {
			ScheduleList sl = (ScheduleList) this.activity ;
			sl.adapter.updateSchedule(modifiedSchedule) ;
			if ((sl.displayedSchedule != null) 
					&& (sl.displayedSchedule.getId() == modifiedSchedule.getId())) {
				sl.displayedSchedule = modifiedSchedule ;
				FragmentManager fm = this.activity.getSupportFragmentManager() ;
				ScheduleDetailsFragment detailsFragment = (ScheduleDetailsFragment) 
						fm.findFragmentById(R.id.schedule_details) ;
				detailsFragment.updateContent() ;
			}// if
		}// handleModifiedScheduleRunnable(Schedule)
		
		@Override
		protected void handleModifiedScheduleStateRunnable(Schedule modifiedSchedule,
				ScheduleUpdateProgress newUpdateState) {
			ScheduleList sl = (ScheduleList) this.activity ;
			// Update queue size and refresh icon
			boolean updateIcon = false ;
			String modifiedName = modifiedSchedule.getName() ;
//			Log.d(TAG, String.format("Before progress: %d/%d", 
//					Integer.valueOf(sl.progress), Integer.valueOf(sl.nTotalSteps))) ;
//			Log.d(TAG, String.format("[%s]: %s",  //$NON-NLS-1$
//					modifiedName, modifiedSchedule.getState())) ;
			switch (modifiedSchedule.getState()) {
			case WAITING_FOR_UPDATE:
				updateIcon = sl.updateQueue.isEmpty() ;
				if (updateIcon) {
					sl.progress = sl.nTotalSteps = 0 ;
					sl.updateProgressBar.init() ;
					sl.handler.postDelayed(sl.updateProgressBar, PROGRESS_UPDATE_DELAY) ; 
				}// if
				sl.updateQueue.add(modifiedSchedule) ;
				sl.setSupportProgressBarVisibility(true) ;
				sl.nTotalSteps = 
						(N_PROGRESS_STEPS_PER_SCHEDULE_UPDATE * sl.updateQueue.size()) ;
				break ;
			case UPDATED:
			case NOT_UPDATED:
				for(Schedule s : sl.updateQueue) {
//					Log.d(TAG, String.format("-- [%s]: %s",
//							s.getName(), s.getState())) ;
					if (s.getName().equals(modifiedName) 
							&& s.getState().equals(ScheduleState.WAITING_FOR_UPDATE)) {
						sl.progress += N_PROGRESS_STEPS_PER_SCHEDULE_UPDATE ;
					}// if
				}// for
				sl.updateQueue.remove(modifiedSchedule) ;
				break ;
			case UPDATING:
				if (newUpdateState.equals(ScheduleUpdateProgress.STEP_1)) {
					for(Schedule s : sl.updateQueue) {
						if (s.getName().equals(modifiedName)) {
							s.setState(ScheduleState.UPDATING) ;
						}// if
					}// for
					updateIcon = false ;
				} else {
					updateIcon = newUpdateState.equals(ScheduleUpdateProgress.STEP_6)
							&& sl.updateQueue.isEmpty() ;
				}// if
				sl.progress += 1 ;
				break ;
			default:
			}// switch
//			Log.d(TAG, String.format("After  progress: %d/%d", 
//					Integer.valueOf(sl.progress), Integer.valueOf(sl.nTotalSteps))) ;
			if (updateIcon) {
				this.activity.invalidateOptionsMenu() ;
			}// if
			
//			if (sl.progress < sl.nTotalSteps)  {
//				int realProgress = ((android.view.Window.PROGRESS_END 
//						- android.view.Window.PROGRESS_START) / 100) 
//						* (sl.progress * 100 / sl.nTotalSteps) ;
//				sl.setSupportProgress(realProgress) ;
//				Log.d(TAG, String.format("Progress: %d of %d (%d of %d)", //$NON-NLS-1$
//						sl.progress, sl.nTotalSteps,
//						realProgress, android.view.Window.PROGRESS_END 
//						- android.view.Window.PROGRESS_START)) ;
//			} else {
//				sl.nTotalSteps = 0 ;
//				sl.progress = 0 ;
//				sl.setSupportProgressBarVisibility(false) ;
//			}// if
			
//			Log.d(TAG, String.format("Modified schedule (%s) state: %s",  //$NON-NLS-1$
//					modifiedSchedule.getName(), modifiedSchedule.getState())) ;
//			Log.d(TAG, String.format(">> queue size: %d",  //$NON-NLS-1$
//					this.activity.updateQueue.size())) ;
			
			sl.adapter.updateScheduleState(modifiedSchedule) ;
			Schedule ds = sl.displayedSchedule ;
			if ((ds != null) && (ds.getId() == modifiedSchedule.getId())) {
				sl.displayedSchedule = modifiedSchedule ;
				sl.updateActionModeState() ;
			}// if
		}// handleModifiedScheduleStateRunnable(Schedule)

	}// class AdeWebServiceListenerAdapter
	
	private class ProgressUpdateRunnable implements Runnable {
		
		private final int STEP = 2 ;
		
		protected int currentProgress ;
		
		protected ProgressUpdateRunnable() {
			super() ;
			this.currentProgress = android.view.Window.PROGRESS_END ;
		}// ProgressUpdateRunnable()
		
		public void init() {
			this.currentProgress = 0 ;
		}// init()
		
		@Override
		public void run() {
			ScheduleList sl = ScheduleList.this ;
			int scale = ((android.view.Window.PROGRESS_END 
					- android.view.Window.PROGRESS_START) / 100)  ;
			int realProgress = scale * (sl.progress * 100 / sl.nTotalSteps) ;
			if (this.currentProgress < realProgress) {
				this.currentProgress += this.STEP * scale ;
				sl.setSupportProgress(this.currentProgress) ;
			}// if
			if (this.currentProgress < android.view.Window.PROGRESS_END) {
				sl.handler.postDelayed(this, PROGRESS_UPDATE_DELAY) ;
			} else {
				sl.invalidateOptionsMenu() ;
			}// if
		}// run()
	}// class ProgressUpdateRunnable

}// class ScheduleList